<?php

namespace app\command\workerman\process\httpServer;

use think\App;
use Workerman\Connection\TcpConnection;
use Workerman\Protocols\Http\Request;
use Workerman\Worker;

class Handler
{
	protected App $app;

	protected string $serverName = 'beautiful-girl';

	protected int $maxRequestCount = 10000;

	/**
	 * 应用根目录
	 * @var string
	 */
	protected string $rootPath = '';

	/**
	 * 网站访问目录
	 * @var string
	 */
	protected string $publicPath = '';

    protected bool $allowAccessStatic = false;

	public function __construct(array $config = [])
	{
		if (isset($config['serverName'])) $this->serverName = $config['serverName'];

		if (isset($config['maxRequestCount'])) $this->maxRequestCount = $config['maxRequestCount'];

        if (isset($config['allowAccessStatic'])) $this->allowAccessStatic = $config['allowAccessStatic'];

		if (!isset($config['rootPath'])) {
			$this->rootPath = \think\facade\App::getRootPath();
		} else {
			$this->rootPath = $config['rootPath'];
		}
		if (!isset($config['publicPath'])) {
			$this->publicPath = \think\facade\App::getRootPath() . 'public';
		} else {
			$this->publicPath = $config['publicPath'];
		}
		if (empty($this->rootPath) || empty($this->publicPath)) {
			posix_kill(posix_getppid(), SIGINT);
			throw new \Exception('not set root dir or public dir');
		}
	}

	public function onWorkerStart(): void
	{
		$this->app = new Application($this->rootPath);

		$this->app->initialize();

		$this->app->workermanResponse = \app(Response::class);

		$this->app->bind([
			'think\Cookie' => Cookie::class,
			'think\Request' => \app\command\workerman\process\httpServer\Request::class
		]);
	}

	public function onMessage(TcpConnection $connection, Request $request): void
	{
		// 访问资源文件
		$file = $this->publicPath . DIRECTORY_SEPARATOR . $request->uri();
		if (is_file($file) && $this->allowAccessStatic) {
			// 检查if-modified-since头判断文件是否修改过
			if (!empty($if_modified_since = $request->header('if-modified-since'))) {
				$modified_time = date('D, d M Y H:i:s', filemtime($file)) . ' ' . \date_default_timezone_get();
				// 文件未修改则返回304
				if ($modified_time === $if_modified_since) {
					$connection->send($this->app->workermanResponse->withStatus(304));
					return;
				}
			}

			// 文件修改过或者没有if-modified-since头则发送文件
			$connection->send(
				$this->app->workermanResponse
					->withStatus(200)
					->withHeaders([
						'Server' => $this->serverName
					])
					->withFile($file)
			);
		} else {
			$this->app->setServerName($this->serverName);

			// 兼容 php://input
			$this->app->workermanRequest = $request;
			$this->app->request->_wmSetRawInput($request->rawBody());

			// 执行app逻辑
			$this->app->worker($connection, $request);
		}

		// 请求一定数量后，退出进程重开，防止内存溢出
		static $requestCount;
		if (++$requestCount > $this->maxRequestCount) {
			Worker::stopAll();
		}
	}
}